﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;

namespace CorporationWars
{
    [Serializable]
    public class RealEstate
    {
        /// <summary>
        /// Name of property
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// Location
        /// </summary>
        public GeoLocation Location { get; set; }
        /// <summary>
        /// How much to buy it
        /// </summary>
        public decimal PurcahsePrice { get; set; }
        /// <summary>
        /// How much it can be sold for
        /// </summary>
        public decimal SalePrice { get; set; }
        /// <summary>
        /// Technology level 1-24
        /// </summary>
        public int TechLevel { get; set; }
        /// <summary>
        /// Cycle to Cycle running costs if staffed else halved
        /// </summary>
        protected decimal _RunningCost { get; set; }
        public decimal RunningCost { get { return (IsStaffed ? _RunningCost : _RunningCost / 2) + ((_RunningCost / 4) * (decimal)((1f - Condition) * 10)); } set { _RunningCost = value; } }
        /// <summary>
        /// Cycle to Cycle running costs if mothballed
        /// </summary>
        public decimal MothBallCost { get; set; }
        /// <summary>
        /// cost asociated with running and maintaingn the real estate
        /// </summary>
        protected decimal _Proffitablity = 0;
        public virtual decimal Proffitablity { get { return _Proffitablity; } }
        /// <summary>
        /// Is it moth balled
        /// </summary>
        public virtual bool IsMothballed { get; set; }
        protected bool _IsStaffed { get; set; }

        /// <summary>
        /// State of disrepair 1 = imaculate
        /// </summary>
        public float Condition { get; set; }

        /// <summary>
        /// Cost to repair realestate
        /// </summary>
        public decimal RepairCosts { get { return Math.Round((RunningCost * TechLevel) * (decimal)((1f - Condition) * 10)); } }

        /// <summary>
        /// Cost to populate with new staff.
        /// </summary>
        public decimal CostToStaff { get; set; }

        public bool IsStaffed
        {
            get { return _IsStaffed; }
            set
            {
                _IsStaffed = value;
                if(IsMothballed != !_IsStaffed)
                    IsMothballed = !_IsStaffed;
            }
        }

        public RealEstate() { }

        public RealEstate(string name, GeoLocation location)
        {
            Name = name;
            Location = location;
        }

        public static Housing GenerateHousing(string name, GeoLocation location)
        {
            Random rnd = new Random(DateTime.Now.Millisecond);
            decimal purchasePrice = 0;  // Ranges from 3-100 million * tl
            decimal salePrice = 0;      // purchase price / 3
            int tl = 1;                 // 1 - 5
            decimal runningCost = 0;    // salePrice / tl
            decimal mothballCost = 0;   // runncost / 4
            bool occupied = false;      // has tenants
            bool staffed = false;       // has maintenance staff
            decimal costToStaff = 0;    // saleprice / 2
            float condition = 1;

            tl = rnd.Next(1, 6);
            purchasePrice = (decimal)MathHelper.Lerp(3000000, 100000000, (float)rnd.NextDouble()) * tl;
            salePrice = purchasePrice / 3;
            runningCost = salePrice / tl;
            mothballCost = runningCost / 4;
            occupied = rnd.Next(0, 2) == 1;
            staffed = rnd.Next(0, 2) == 1;
            costToStaff = salePrice / 2;
            condition = MathHelper.Lerp(.5f, 1, (float)rnd.NextDouble());

            return new Housing(name, location)
            {
                PurcahsePrice = purchasePrice,
                SalePrice = salePrice,
                TechLevel = tl,
                RunningCost = runningCost,
                MothBallCost = mothballCost,
                IsOccupied = occupied,
                IsStaffed = staffed,
                CostToStaff = costToStaff,
                Condition = condition,
            };
        }

        public static Manufacture GenerateManufacture(string name, GeoLocation location)
        {
            Random rnd = new Random(DateTime.Now.Millisecond);

            decimal purchasePrice = 0;  // Ranges from 300-1000 million * tl
            decimal salePrice = 0;      // purchase price / 8
            int tl = 1;                 // 1 - 24
            decimal runningCost = 0;    // salePrice / tl
            decimal mothballCost = 0;   // runncost / 4
            bool staffed = false;       // has maintenance staff
            decimal costToStaff = 0;    // saleprice / 1.7
            float condition = 1;

            tl = rnd.Next(1, 25);
            purchasePrice = (decimal)MathHelper.Lerp(300000000, 1000000000, (float)rnd.NextDouble()) * tl;
            salePrice = purchasePrice / 8;
            runningCost = salePrice / tl;
            mothballCost = runningCost / 4;
            staffed = rnd.Next(0, 2) == 1;
            costToStaff = salePrice / 1.7m;
            condition = MathHelper.Lerp(.5f, 1, (float)rnd.NextDouble());

            return new Manufacture()
            {
                PurcahsePrice = purchasePrice,
                SalePrice = salePrice,
                TechLevel = tl,
                RunningCost = runningCost,
                MothBallCost = mothballCost,
                IsStaffed = staffed,
                CostToStaff = costToStaff,
                Condition = condition,
            };
        }

        public static Warehouse GenerateWarehouse(string name, GeoLocation location)
        {
            Random rnd = new Random(DateTime.Now.Millisecond);

            decimal purchasePrice = 0;  // Ranges from 30-100 million * tl
            decimal salePrice = 0;      // purchase price / 8
            int tl = 1;                 // 1 - 15
            decimal runningCost = 0;    // salePrice / tl
            decimal mothballCost = 0;   // runncost / 4
            bool staffed = false;       // has maintenance staff
            decimal costToStaff = 0;    // saleprice / 2
            float condition = 1;

            tl = rnd.Next(1, 16);
            purchasePrice = (decimal)MathHelper.Lerp(30000000, 100000000, (float)rnd.NextDouble()) * tl;
            salePrice = purchasePrice / 8;
            runningCost = salePrice / tl;
            mothballCost = runningCost / 4;
            staffed = rnd.Next(0, 2) == 1;
            costToStaff = salePrice / 2.25m;
            condition = MathHelper.Lerp(.5f, 1, (float)rnd.NextDouble());

            return new Warehouse()
            {
                PurcahsePrice = purchasePrice,
                SalePrice = salePrice,
                TechLevel = tl,
                RunningCost = runningCost,
                MothBallCost = mothballCost,
                IsStaffed = staffed,
                CostToStaff = costToStaff,
                Condition = condition,
            };
        }

        public static ResearchFacility GenerateResearchFacility(string name, GeoLocation location)
        {
            Random rnd = new Random(DateTime.Now.Millisecond);

            decimal purchasePrice = 0;  // Ranges from 100-500000000 million * tl
            decimal salePrice = 0;      // purchase price / 8
            int tl = 1;                 // 1 - 24
            decimal runningCost = 0;    // salePrice / tl
            decimal mothballCost = 0;   // runncost / 4
            bool staffed = false;       // has maintenance staff
            decimal costToStaff = 0;    // saleprice / 2
            float condition = 1;

            tl = rnd.Next(1, 25);
            purchasePrice = (decimal)MathHelper.Lerp(100000000, 500000000, (float)rnd.NextDouble()) * tl;
            salePrice = purchasePrice / 8;
            runningCost = salePrice / tl;
            mothballCost = runningCost / 4;
            staffed = rnd.Next(0, 2) == 1;
            costToStaff = salePrice / .25m;
            condition = MathHelper.Lerp(.5f, 1, (float)rnd.NextDouble());

            return new ResearchFacility()
            {
                PurcahsePrice = purchasePrice,
                SalePrice = salePrice,
                TechLevel = tl,
                RunningCost = runningCost,
                MothBallCost = mothballCost,
                IsStaffed = staffed,
                CostToStaff = costToStaff,
                Condition = condition,
            };
        }

        public static TransportHub GenerateResearchTransportHub(string name, GeoLocation location)
        {
            Random rnd = new Random(DateTime.Now.Millisecond);

            decimal purchasePrice = 0;  // Ranges from 100-500000000 million * tl
            decimal salePrice = 0;      // purchase price / 8
            int tl = 1;                 // 1 - 24
            decimal runningCost = 0;    // salePrice / tl
            decimal mothballCost = 0;   // runncost / 4
            bool staffed = false;       // has maintenance staff
            decimal costToStaff = 0;    // saleprice / 2
            float condition = 1;

            tl = rnd.Next(1, 25);
            purchasePrice = (decimal)MathHelper.Lerp(100000000, 1500000000, (float)rnd.NextDouble()) * tl;
            salePrice = purchasePrice / 8;
            runningCost = salePrice / tl;
            mothballCost = runningCost / 4;
            staffed = rnd.Next(0, 2) == 1;
            costToStaff = salePrice / 2;
            condition = MathHelper.Lerp(.5f, 1, (float)rnd.NextDouble());

            return new TransportHub()
            {
                PurcahsePrice = purchasePrice,
                SalePrice = salePrice,
                TechLevel = tl,
                RunningCost = runningCost,
                MothBallCost = mothballCost,
                IsStaffed = staffed,
                CostToStaff = costToStaff,
                Condition = condition,
            };
        }
    }

    [Serializable]
    public class Housing : RealEstate
    {
        /// <summary>
        /// cost asociated with running and maintaingn the real estate
        /// if mothballed or not occupied = 0 if not the running coat * 1.125
        /// </summary>
        public override decimal Proffitablity { get { return IsMothballed || !IsOccupied ? 0 : (SalePrice / TechLevel) * 1.0125m; } }

        public override bool IsMothballed
        {
            get
            {
                return base.IsMothballed;
            }
            set
            {
                base.IsMothballed = value;
                if (base.IsMothballed && IsOccupied)
                    IsOccupied = false;
            }
        }

        /// <summary>
        /// Runcost * 
        /// </summary>
        public virtual decimal CostToOccupy { get { return Math.Round(((RunningCost / 2) * TechLevel) * (decimal)((1.0125f - Condition) * 10)); } }
       
        protected bool _IsOccupied { get; set; }
        /// <summary>
        /// Is the unit populated?
        /// </summary>
        public bool IsOccupied
        {
            get { return _IsOccupied; }
            set
            {
                _IsOccupied = value;
                if (IsMothballed != !_IsOccupied)
                    IsMothballed = !_IsOccupied;
            }
        }

        public Housing() : base() { }
        public Housing(string name, GeoLocation location) : base(name,location) { }
    }

    [Serializable]
    public class Manufacture : RealEstate
    {
        /// <summary>
        /// cost asociated with running and maintaingn the real estate
        /// if mothballed or not occupied = 0 if not the running coat * 1.125
        /// </summary>
        public override decimal Proffitablity { get { return IsMothballed ? 0 : (SalePrice / TechLevel) * 1.0125m; } }

        public Manufacture() : base() { }
        public Manufacture(string name, GeoLocation location) : base(name, location) { }
    }

    [Serializable]
    public class Warehouse : RealEstate
    {
        public override decimal Proffitablity { get { return IsMothballed ? 0 : (SalePrice / TechLevel) * 1.01m; } }
        public Warehouse() : base() { }
        public Warehouse(string name, GeoLocation location) : base(name, location) { }
    }

    [Serializable]
    public class ResearchFacility : RealEstate
    {
        public ResearchFacility() : base() { }
        public ResearchFacility(string name, GeoLocation location) : base(name, location) { }
    }

    [Serializable]
    public class TransportHub : RealEstate
    {
        public TransportHub() : base() { }
        public TransportHub(string name, GeoLocation location) : base(name, location) { }
    }

    [Serializable]
    public class PowerStation : RealEstate
    {
        public PowerStation() : base() { }
        public PowerStation(string name, GeoLocation location) : base(name, location) { }
    }
}
